﻿#region License

// PentaBiz - Sustainable Software Development Framework Copyright (C) 2013 Zoltán Csizmazia
// 
// This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
// 
// This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 

#endregion

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Threading;
using Fluent;
using PentaBiz.Studio.Services.Plugins.Models;

namespace PentaBiz.Studio.Services.Plugins
{
    public partial class PluginManager
    {
        private readonly ObservableCollection<PluginCommandModel> _pluginCommandModels =
            new ObservableCollection<PluginCommandModel>();

        private readonly List<PluginTypeSelector> _pluginCommandTypes = new List<PluginTypeSelector>();

        public List<PluginTypeSelector> PluginCommandTypes
        {
            get { return _pluginCommandTypes; }
        }

        public ObservableCollection<PluginCommandModel> PluginCommandModels
        {
            get { return _pluginCommandModels; }
        }

        public void LoadPluginCommand(PluginTypeSelector pluginTypeSelector)
        {
            var pluginPackage = pluginPackages[pluginTypeSelector.PluginAssemblyName];
            PluginHostProxy pluginHost = _pluginHostProxies[pluginPackage];

            PluginCommandModel pluginServiceModel = pluginHost.LoadPluginCommand(this, pluginTypeSelector);
            PluginCommandModels.Add(pluginServiceModel);
        }


        partial void InitializePluginCommands()
        {
            //register plugin control types
            foreach (var pluginHostProxy in _pluginHostProxies)
            {
                _pluginCommandTypes.AddRange(pluginHostProxy.Value.GetPluginCommandTypeSelectors());
            }


            foreach (var pluginTypeSelector in _pluginCommandTypes)
            {
                LoadPluginCommand(pluginTypeSelector);
            }

            PluginCommandModels.CollectionChanged += OnPluginCollectionChanged;


            //now build the ribbon
            var pluginCommandModelGroups = from p in PluginCommandModels
                                           group p by p.Model.Category
                                           into categoryGroup
                                           select new
                                               {
                                                   Category = categoryGroup.Key,
                                                   Groups = from m in categoryGroup
                                                            group m by m.Model.Group
                                                            into gr
                                                            select new
                                                                {
                                                                    Group = gr.Key,
                                                                    Items = gr
                                                                }
                                               };


            //build ribbon menu for the plugin commands
            foreach (var pluginCommandModelGroup in pluginCommandModelGroups)
            {
                var t = new RibbonTabItem
                    {
                        Header = pluginCommandModelGroup.Category,
                        ReduceOrder = ""
                    };

                foreach (var v in pluginCommandModelGroup.Groups)
                {
                    var g = new RibbonGroupBox {Header = v.Group};

                    foreach (var commandModelGroup in v.Items)
                    {
                        var button = new Button {};
                        button.Header = commandModelGroup.Model.Title;
                        button.ToolTip = commandModelGroup.Model.Description;
                        button.SetBinding(ButtonBase.CommandProperty, new Binding("PluginCommandCommand")
                            {
                                Source = commandModelGroup,
                                Mode = BindingMode.OneWay,
                            });
                        g.Items.Add(button);

                        var pluginPackage = pluginPackages[commandModelGroup.PluginTypeSelector.PluginAssemblyName];
                        var pluginHost = _pluginHostProxies[pluginPackage];
                        //on host terminate remove the service from the screen
                        pluginHost.PluginHostExit += (o, e) =>
                                                     Dispatcher.BeginInvoke(() =>
                                                         {
                                                             BindingOperations.ClearBinding(button,
                                                                                            ButtonBase.CommandProperty);
                                                             g.Items.Remove(button);
                                                             PluginCommandModels.Remove(commandModelGroup);
                                                         });
                    }
                    t.Groups.Add(g);
                }

                _ribbon.Tabs.Add(t);
            }
        }
    }
}